﻿///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2023, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Специализированный модуль для организации процесса подтверждения операций
// Реализован механизм встраивания в существующие формы (БСП)
// Поддержаны самостоятельные формы подтверждения в базовом функционале облачной подписи
////////////////////////////////////////////////////////////////////////////////

#Область ПрограммныйИнтерфейс

#Область ДляВызоваИзДругихПодсистем

// Следующие процедуры и функции предназначены для интеграции с 1С-Отчетность

// Функция подготовки данных цикла подтверждения.
//
// Параметры:
//  НастройкиПользователя			- Структура
//
// Возвращаемое значение:
//   Структура:
//    * ЭтапЦикла					- Строка - варианты: 
//										Инициализация, Начало, Выбор, Ошибка, Окончание, ВводКода, Проверка, Предупреждение, Ожидание, Отказ.
//    * СрокДействия				- Неопределено, Дата - срок действия транзакции или подтверждения
//    * Идентификатор				- Строка - идентификатор аутентификационного испытания
//    * ИдентификаторТранзакции		- Строка - идентификатор транзакции требующей подтверждения
//    * Ошибка						- Строка - описание ошибки полученной при разборе результат запроса
//    * КодОшибки					- Строка - код ошибки полученные при разборе результата запроса
//    * ГрафическийКод				- Строка - полученный QRCode в формате строки Base64 
//    * Заголовок					- Строка - заголовок формы подтверждения полученный от потребителя 
//    * СписокМетодов				- Массив из Структура:
//      ** Тип						- ПеречислениеСсылка.СпособыАвторизацииDSS
//      ** Идентификатор 			- ПеречислениеСсылка.СпособыАвторизацииDSS
//									- Строка
//      ** Адрес					- Булево
//      ** Описание					- Строка 
//    * ДоступныеМетоды				- Массив - допустимые способы подтверждения полученные от потребителя
//    * КодПользователя				- Строка - код подтверждения введенный пользователем
//    * ТипПодтверждения			- Строка - поддерживаемые типы подтверждения: Транзакция, Аутентификация, ПроизвольнаяОперация
//    * ШаблонПодтверждения			- Строка - имя шаблона подтверждения зарегистрированный на сервисе облачной подписи
//    * ОписаниеПодтверждения		- Строка - описание операции подтверждения, полученной от сервиса
//    * ВторичнаяАвторизация		- ПеречислениеСсылка.СпособыАвторизацииDSS - выбранный способ подтверждения
//    * Сертификат					- см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//    * ДанныеДокументов			- Структура, Массив из Структура - с полями: ИмяФайла, АдресХранилища
//    * ПараметрыВариантаВстроенного- Структура - служит для хранения информации встроенного варианта подтверждения
//    * ПериодОпроса				- Число - период опроса результат подтверждения, актуально для мобильных приложений
//    * СрокОпроса					- Дата - время последнего вызова сервиса
//    * ОбновитьРазмерыФормы		- Булево - для встроенного подтверждения, принудительно меняет форму БСП после открытия или смены сертификата
//    * КодЯзыка					- Строка - служебное поле для ускорения работы с формированием строк сообщений
//    * Оформление					- Структура - кеш стилей, служебное
//
Функция ДанныеВторичнойАвторизацииПоУмолчанию(НастройкиПользователя = Неопределено) Экспорт
	
	Результат = Новый Структура();
	Результат.Вставить("ЭтапЦикла", "Начало");
	Результат.Вставить("СрокДействия", Неопределено);
	Результат.Вставить("Идентификатор", Неопределено);
	Результат.Вставить("ГрафическийКод", Неопределено);
	Результат.Вставить("Заголовок", "");
	Результат.Вставить("СписокМетодов", Новый Массив);
	Результат.Вставить("ДоступныеМетоды", СервисКриптографииDSSСлужебный.ДоступныеСпособыВторичнойАвторизации());
	Результат.Вставить("Ошибка", "");
	Результат.Вставить("КодОшибки", "");
	Результат.Вставить("КодПользователя", "");
	Результат.Вставить("ТипПодтверждения", "");
	Результат.Вставить("ШаблонПодтверждения", "");
	Результат.Вставить("ОписаниеПодтверждения", "");
	Результат.Вставить("ВторичнаяАвторизация", Перечисления.СпособыАвторизацииDSS.ПустаяСсылка());
	Результат.Вставить("ИдентификаторТранзакции", "");
	Результат.Вставить("Сертификат", Неопределено);
	Результат.Вставить("ДанныеДокументов", Неопределено);
	Результат.Вставить("ПараметрыВариантаВстроенного", Новый Структура);
	Результат.Вставить("ПериодОпроса", 3);
	Результат.Вставить("СрокОпроса", '19800101');
	Результат.Вставить("ОбновитьРазмерыФормы", Истина);
	Результат.Вставить("КодЯзыка", СервисКриптографииDSSСлужебный.КодЯзыка());
	Результат.Вставить("Оформление", Новый Структура());
	
	Результат.Вставить("ГрафическийКодВладелец", Неопределено);
	Результат.Вставить("ИдентификаторОперации", "");
	Результат.Вставить("ВерсияПодтверждения", 1);
	
	Если НастройкиПользователя <> Неопределено Тогда
		Результат.ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);	
	КонецЕсли;
	
	Результат.Оформление.Вставить("ПоясняющийОшибкуТекст", СервисКриптографииDSSСлужебный.ПолучитьЭлементСтиля("ПоясняющийОшибкуТекст", "Цвет"));
	Результат.Оформление.Вставить("ПодтверждениеОперацииОписаниеЦвет", СервисКриптографииDSSСлужебный.ПолучитьЭлементСтиля("ПодтверждениеОперацииОписаниеЦвет", "Цвет"));

	Возврат Результат;
	
КонецФункции

// Формирует представление списка документа, операция над которыми требует подтверждения
//
// Параметры:
//  ДанныеДокументов - Структура - содержит поле "СписокДокументов" с типом массив
//
// Возвращаемое значение:
//   - Строка
//   - ФорматированнаяСтрока
//
Функция ПолучитьПредставлениеДокументов(ДанныеДокументов) Экспорт
	
	Результат = "";
	
	Если ТипЗнч(ДанныеДокументов) = Тип("Структура") Тогда
		
		КоличествоЭлементов = ДанныеДокументов.СписокДокументов.Количество();
		Если КоличествоЭлементов = 1 Тогда
			НоваяСтрока = ДанныеДокументов.СписокДокументов[0];
		ИначеЕсли КоличествоЭлементов > 0 Тогда
			
			ПредставлениеСтроки = СтрокаСЧислом(
						НСтр("ru = ';%1 документ;;%1 документа;%1 документов;%1 документов'", СервисКриптографииDSSСлужебный.КодЯзыка()),
						КоличествоЭлементов, 
						ВидЧисловогоЗначения.Количественное);
						
			НоваяСтрока = ОписаниеДокументаПоУмолчанию();
			НоваяСтрока.НаименованиеФайла = ПредставлениеСтроки;
			НоваяСтрока.НавигационнаяСсылка = "Всего" + XMLСтрока(КоличествоЭлементов);
		КонецЕсли;
		
		Результат = ПредставлениеДокумента(НоваяСтрока);
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Формирует представление сертификата с помощь которого операция требует подтверждения
//
// Параметры:
//  Сертификат - см. СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя
//
// Возвращаемое значение:
//   Строка
//
Функция ПолучитьПредставлениеСертификата(Сертификат) Экспорт

	ПредставлениеСертификата = "";
	
	Если ЗначениеЗаполнено(Сертификат) Тогда
		ПредставлениеСертификата = Сертификат.Представление;
	КонецЕсли;	

	Возврат ПредставлениеСертификата;
	
КонецФункции

// Формирует представление одиночного документа для форм подтверждения
//
// Параметры:
//  СтруктураДокумента - Структура - содержит поля "НаименованиеФайла" и "НавигационнаяСсылка"
//
// Возвращаемое значение:
//   ФорматированнаяСтрока
//
Функция ПредставлениеДокумента(СтруктураДокумента) Экспорт
	
	ОбщаяСтрока = "<a href = """ + СтруктураДокумента.НавигационнаяСсылка + """" + ">" + СтруктураДокумента.НаименованиеФайла + "</a>";
	Результат = СтроковыеФункции.ФорматированнаяСтрока(ОбщаяСтрока);
	
	Возврат Результат;
	
КонецФункции

// Формирует структура описывающую одиночный документ для операций подтверждения
//
// Возвращаемое значение:
//   Структура:
//    * НаименованиеФайла 	- Строка - представление документа
//    * НавигационнаяСсылка 	- Строка - навигационная ссылка позволяющая открыть документ
//
Функция ОписаниеДокументаПоУмолчанию() Экспорт
	
	Результат = Новый Структура;
	Результат.Вставить("НаименованиеФайла", "");
	Результат.Вставить("НавигационнаяСсылка", "");
	
	Возврат Результат;
	
КонецФункции

// Возвращает описание сертификата, если он является сертификатом облака
//
// Параметры:
//  СертификатСсылка - СправочникСсылка.СертификатыКлючейЭлектроннойПодписиИШифрования
//
// Возвращаемое значение:
//   Структура:
//    * Облачный - Булево
//    * Ошибка - Строка - содержит описание проблемы выбранного облачного сертификата
//    * Идентификатор - Число - идентификатор облачного сертификата
//    * УчетнаяЗапись - СправочникСсылка.УчетныеЗаписиDSS - связанный с данным сертификатом учетная запись
//
Функция ПроверитьВыбранныйСертификат(СертификатСсылка) Экспорт
	
	КодЯзыка = СервисКриптографииDSSСлужебный.КодЯзыка();
	РеквизитыСертификата = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(СертификатСсылка, "Программа, Отпечаток", Истина);
	Отпечаток = СервисКриптографииDSSКлиентСервер.ТрансформироватьОтпечаток(РеквизитыСертификата.Отпечаток);
	
	Результат = ДанныеСертификатаПоУмолчанию();
	Результат.Отпечаток = Отпечаток;
	
	Если НЕ СервисКриптографииDSSСлужебный.ПроверитьПраво("СертификатыПользователяDSS") Тогда
		Возврат Результат;
	КонецЕсли;
	
	ТекстЗапроса = 
	"ВЫБРАТЬ РАЗРЕШЕННЫЕ
	|	СертификатыПользователяDSS.УчетнаяЗаписьDSS КАК УчетнаяЗаписьDSS,
	|	СертификатыПользователяDSS.Идентификатор КАК Идентификатор
	|ИЗ
	|	РегистрСведений.СертификатыПользователяDSS КАК СертификатыПользователяDSS
	|ГДЕ
	|	СертификатыПользователяDSS.Отпечаток = &Отпечаток
	|	И СертификатыПользователяDSS.УчетнаяЗаписьDSS = &Программа
	|
	|ОБЪЕДИНИТЬ ВСЕ
	|
	|ВЫБРАТЬ ПЕРВЫЕ 1
	|	СертификатыПользователяDSS.УчетнаяЗаписьDSS,
	|	СертификатыПользователяDSS.Идентификатор
	|ИЗ
	|	РегистрСведений.СертификатыПользователяDSS КАК СертификатыПользователяDSS
	|ГДЕ
	|	СертификатыПользователяDSS.Отпечаток = &Отпечаток
	|	И СертификатыПользователяDSS.УчетнаяЗаписьDSS <> &Программа";
	
	Запрос = Новый Запрос(ТекстЗапроса);
	Запрос.УстановитьПараметр("Отпечаток", Отпечаток);
	Запрос.УстановитьПараметр("Программа", РеквизитыСертификата.Программа);
	Выборка = Запрос.Выполнить().Выбрать();
	
	Если Выборка.Следующий() Тогда
		
		ПредставлениеСертификата = НСтр("ru = 'Для сертификата:'", КодЯзыка) + " " + СокрЛП(СертификатСсылка);
		Если НЕ ЗначениеЗаполнено(Выборка.УчетнаяЗаписьDSS) Тогда
			Результат.Вставить("Ошибка", СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(Неопределено, "СертификатБезУчетнойЗаписи", ПредставлениеСертификата));
		ИначеЕсли РеквизитыСертификата.Программа <> Выборка.УчетнаяЗаписьDSS Тогда
			Результат.Вставить("Ошибка", СервисКриптографииDSSСлужебный.ПолучитьОписаниеОшибки(Неопределено, "ЧужойСертификат", ПредставлениеСертификата));
		Иначе
			Результат.Вставить("Облачный", Истина);
			Результат.Вставить("Идентификатор", Выборка.Идентификатор);
			Результат.Вставить("УчетнаяЗапись", Выборка.УчетнаяЗаписьDSS);
		КонецЕсли;
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Дополняет настройки пользователя, в случае если нет элемента справочника.
// Например, в процессе восстановления учетной записи по логину.
// 
// Параметры:
//  КонтекстФормы 	- ФормаКлиентскогоПриложения, Неопределено - в данных формы должны быть реквизит НастройкиПользователя
//  СерверПодписи	- СправочникСсылка.ЭкземплярыСервераDSS, Структура - содержит описание сервера для указанного логина, если 
//					передана структура, то она должна содержать те же поля в функции СервисКриптографииDSSСлужебный.ПолучитьВсеСерверы.
//  Логин			- Строка - имя пользователя сервиса облачной подписи
//
Процедура ДополнитьНастройкиПользователя(КонтекстФормы, СерверПодписи, Логин) Экспорт
	
	РеестрИмен = ОпределитьБазовыеРеквизиты(КонтекстФормы);
	РеквизитыФормы = Новый Структура;
	РеквизитыФормы.Вставить(РеестрИмен.НастройкиПользователя);
	РеквизитыФормы.Вставить(РеестрИмен.ДанныеПодтверждения);
	
	Если КонтекстФормы <> Неопределено Тогда
		ЗаполнитьЗначенияСвойств(РеквизитыФормы, КонтекстФормы);
	КонецЕсли;	
	
	Если ТипЗнч(СерверПодписи) = Тип("СправочникСсылка.ЭкземплярыСервераDSS") Тогда
		ВсеСерверы = СервисКриптографииDSSСлужебный.ПолучитьВсеСерверы(Новый Структура("Ссылка", СерверПодписи));
		Если ВсеСерверы.Количество() > 0 Тогда
			ДанныеСервера = Новый Структура();
			ТекущаяСтрока = ВсеСерверы[0];
			Для Каждого СтрокаКолонки Из ВсеСерверы.Колонки Цикл
				ДанныеСервера.Вставить(СтрокаКолонки.Имя, ТекущаяСтрока[СтрокаКолонки.Имя]);
			КонецЦикла;	
		КонецЕсли;
	Иначе
		ДанныеСервера = СерверПодписи;
	КонецЕсли;
	
	Если КонтекстФормы = Неопределено Тогда
		КонтекстФормы = СервисКриптографииDSS.НастройкиПользователяПоУмолчанию();
		СервисКриптографииDSSСлужебный.ДополнитьНастройкиПользователя(КонтекстФормы, ДанныеСервера, Логин);
	ИначеЕсли РеквизитыФормы[РеестрИмен.НастройкиПользователя] <> Неопределено Тогда
		СервисКриптографииDSSСлужебный.ДополнитьНастройкиПользователя(КонтекстФормы[РеестрИмен.НастройкиПользователя], ДанныеСервера, Логин);
	КонецЕсли;
	
	Если РеквизитыФормы[РеестрИмен.ДанныеПодтверждения] <> Неопределено Тогда
		КонтекстФормы[РеестрИмен.ДанныеПодтверждения].ШаблонПодтверждения = КонтекстФормы[РеестрИмен.НастройкиПользователя].ШаблонПодтверждения;
	КонецЕсли;	

КонецПроцедуры	

// Подготавливает существующие формы для процедуры подтверждения при создании формы
// Добавляет реквизиты, элементы формы, заполняет нужные данные.
// Для полноценного работы встроенного подтверждения необходимы доработки в целевой форме:
//	добавить процедуры для обработки событий добавленных элементов
//		Подключаемый_ПодтверждениеОбработкаКоманды
//		Подключаемый_ПодтверждениеОбработкаНавигационнойСсылки
//		Подключаемый_ПодтверждениеПриИзменении
//		Подключаемый_ПодтверждениеОбработчикОжидания
//	добавить вызовы в существующие события
//		ПриСозданииНаСервере
//		ПриОткрытии
//		ОбработкаОповещения, добавить обработку событий "ПодтверждениеВыполнитьОсновнуюОперацию", "ПодтверждениеАвторизация"
//	также надо позаботиться о заполнении структуры "ДанныеСертификата"
//		например при изменении сертификата, см. ПодтверждениеПриИзмененииСертификата.
// Пример реализации встроенного подтверждения можно посмотреть в форме Справочники.СертификатыКлючейЭлектроннойПодписиИШифрования.ПодписаниеДанных.
// 
// Параметры:
//  КонтекстФормы 			- ФормаКлиентскогоПриложения - форма куда будут добавлены элементы для организации подтверждения
//  ТипОперации				- Строка - поддерживаются следующие варианты "Шифрование", "Расшифрование", "Подписание", "Аутентификация"
//  ГруппаСертификата 		- Строка - имя группы, где расположен элементы формы с сертификатом
//  ИмяГруппы				- Строка - имя группы куда будут размещены элементы
//  ИмяГруппыВторой			- Строка - имя дополнительной группы для размещения элементов
//  ИмяГруппаКоманды		- Строка - имя группы для размещения кнопок
//  ПараметрыОперации 		- Неопределено, Структура - позволяет передать дополнительные параметры вызова:
//    * ЕстьРазделители 	- Булево - выводить ли разделителя для обозначения последовательности операций
//
Процедура ПодготовитьГруппуПодтверждения(КонтекстФормы, 
										ТипОперации, 
										ГруппаСертификата, 
										ИмяГруппы, 
										ИмяГруппыВторой = "", 
										ИмяГруппаКоманды = "",
										ПараметрыОперации = Неопределено) Экспорт
	
	Если НЕ ФормаПодготовлена(КонтекстФормы) Тогда
		КонвертироватьИмена = СервисКриптографииDSSКлиентСервер.ПолучитьПолеСтруктуры(ПараметрыОперации, "КонвертироватьИмена", Истина);
		ИменаЭлементовФормы = СервисКриптографииDSSКлиентСервер.ПолучитьПолеСтруктуры(ПараметрыОперации, "ИменаЭлементовФормы", Новый Структура);
		ЕстьРазделители = СервисКриптографииDSSКлиентСервер.ПолучитьПолеСтруктуры(ПараметрыОперации, "ЕстьРазделители", Истина);
		
		ПодготовитьГруппуПодтвержденияРеквизиты(КонтекстФормы, КонвертироватьИмена);
		РеестрИмен = ОпределитьБазовыеРеквизиты(КонтекстФормы);
		ПодготовитьГруппуПодтвержденияИнициализация(КонтекстФормы);
		
		ЕстьРазделители = ТипОперации <> "Шифрование" И ТипОперации <> "Проверка" И ЕстьРазделители;
							
		ИменаГруппКонтейнера = КонтекстФормы[РеестрИмен.ИменаГруппКонтейнера]; 
		ИменаГруппКонтейнера.Вставить("ГруппаСертификата", ГруппаСертификата);
		ИменаГруппКонтейнера.Вставить("КонтейнерЭлементов1", ИмяГруппы);
		ИменаГруппКонтейнера.Вставить("КонтейнерЭлементов2", ИмяГруппыВторой);
		ИменаГруппКонтейнера.Вставить("ГруппаКоманды", ИмяГруппаКоманды);
		ИменаГруппКонтейнера.Вставить("ЕстьРазделители", ЕстьРазделители);
		
		КонтекстФормы[РеестрИмен.ПодтверждениеТипОперации] = ТипОперации;
		Если ТипОперации <> "Проверка" Тогда 
			ПодготовитьГруппуПодтвержденияЭлементы(КонтекстФормы, ИменаЭлементовФормы);
		КонецЕсли;
		СервисКриптографииDSSСлужебныйВызовСервера.НачальныеНастройкиФормы(КонтекстФормы.ИмяФормы);
	КонецЕсли;
	
КонецПроцедуры

// Дополняет данные подтверждения для произвольного подтверждения для встроенного варианта
//
// Параметры:
//  КонтекстФормы 				- ФормаКлиентскогоПриложения - содержит реквизиты:
//    * ДанныеПодтверждения		- см. ДанныеВторичнойАвторизацииПоУмолчанию
//    * НастройкиПользователя	- см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//    * Логин					- Строка
//    * СпособПодтверждения		- Строка 
//    							- ПеречислениеСсылка.СпособыАвторизацииDSS
//    * ЗапомнитьПарольЛогина	- Булево
//    * ПарольЛогина			- Строка
//    * ГрафическийКод			- Строка
//  ЗаголовокОперации			- Строка
//  ПервичнаяАвторизация		- Строка
//                      		- ПеречислениеСсылка.СпособыАвторизацииDSS
//  ВторичнаяАвторизация		- Строка
//                      		- ПеречислениеСсылка.СпособыАвторизацииDSS
//  Логин						- Неопределено, Строка - логина пользователя
//  ПараметрыОперации			- Структура:
//    * ТипПодтверждения		- Строка
//
Процедура ДополнитьПроизвольноеПодтверждение(
							КонтекстФормы, 
							ЗаголовокОперации, 
							ПервичнаяАвторизация, 
							ВторичнаяАвторизация, 
							Логин = Неопределено,
							ПараметрыОперации = Неопределено) Экспорт
	
	РеестрИмен = ОпределитьБазовыеРеквизиты(КонтекстФормы);
	ДанныеСертификата = КонтекстФормы[РеестрИмен.ДанныеСертификата];
	ДанныеПодтверждения = КонтекстФормы[РеестрИмен.ДанныеПодтверждения]; // см. СервисКриптографииDSSПодтверждениеСервер.ДанныеВторичнойАвторизацииПоУмолчанию
	НастройкиПользователя = ПолучитьНастройкиПользователяИзФормы(КонтекстФормы, РеестрИмен);
	НастройкиПользователя.ПервичнаяАутентификация = ПолучитьЗначениеПеречисления(ПервичнаяАвторизация);
	
	ДанныеСертификата.Облачный = Истина;
	Если Логин <> Неопределено Тогда
		НастройкиПользователя.Логин = Логин;
		ДанныеПодтверждения.ПараметрыВариантаВстроенного.ЕстьАвторизация = Истина;
	КонецЕсли;	
	
	ДанныеПодтверждения.ТипПодтверждения = СервисКриптографииDSSКлиентСервер.ПолучитьПолеСтруктуры(ПараметрыОперации, "ТипПодтверждения", "ПроизвольнаяОперация");
	ДанныеПодтверждения.ЭтапЦикла = "Инициализация";
	ДанныеПодтверждения.Заголовок = ЗаголовокОперации;
	ДанныеПодтверждения.СрокДействия = СервисКриптографииDSSСлужебный.ДатаСеанса() + 60 * 5;
	ДанныеПодтверждения.Сертификат = СервисКриптографииDSSКлиентСервер.СвойстваСертификатаПользователя();
	ДанныеПодтверждения.Сертификат.ТребуетсяПинКод = Ложь;
	ДанныеПодтверждения.ГрафическийКод = "";
	ДанныеПодтверждения.ГрафическийКодВладелец = Неопределено;
	
	Если ЗначениеЗаполнено(ВторичнаяАвторизация) Тогда
		ДанныеПодтверждения.ДоступныеМетоды = СформироватьСписокМетодовАвторизации(ВторичнаяАвторизация);
	КонецЕсли;	
	
	ТипПодтверждения = СервисКриптографииDSSКлиентСервер.ПолучитьВторичнуюАвторизацию(ДанныеПодтверждения.ВторичнаяАвторизация);
	Если ДанныеПодтверждения.ДоступныеМетоды.Найти(ТипПодтверждения) = Неопределено
		И ДанныеПодтверждения.ДоступныеМетоды.Количество() > 0 Тогда
		ДанныеПодтверждения.ВторичнаяАвторизация = ДанныеПодтверждения.ДоступныеМетоды[0];
	Иначе
		ДанныеПодтверждения.ВторичнаяАвторизация = НастройкиПользователя.ВторичнаяАвторизация;
	КонецЕсли;
	
	КонтекстФормы[РеестрИмен.Логин] = НастройкиПользователя.Ссылка;
	КонтекстФормы[РеестрИмен.ЗапомнитьПарольЛогина] = НастройкиПользователя.ЗапоминатьПароли;
	КонтекстФормы[РеестрИмен.ГрафическийКод] = "";
	ТекущийПароль = Неопределено;
	
	Если НастройкиПользователя.ПервичнаяАутентификация = Перечисления.СпособыАвторизацииDSS.Первичный_СертификатАвторизации Тогда
		ТекущийПароль = НастройкиПользователя.ПарольСертификата;
	Иначе
		ТекущийПароль = НастройкиПользователя.Пароль;
	КонецЕсли;
	
	ЗначениеПароля = СервисКриптографииDSSКлиентСервер.ПолучитьЗначениеПароля(ТекущийПароль, НастройкиПользователя.АвторизованныйПользователь);
	КонтекстФормы[РеестрИмен.ПарольЛогина] = ЗначениеПароля;
	
	КонтекстФормы[РеестрИмен.НастройкиПользователя] = СервисКриптографииDSSСлужебный.ЗакрытьНастройкиПользователя(НастройкиПользователя);
	КонтекстФормы[РеестрИмен.ДанныеПодтверждения] = ДанныеПодтверждения;
	КонтекстФормы[РеестрИмен.СпособПодтверждения] = ДанныеПодтверждения.ВторичнаяАвторизация;
	
КонецПроцедуры

#КонецОбласти

#КонецОбласти

#Область СлужебныйПрограммныйИнтерфейс

#Область СамостоятельныеПодтверждение

// Служебная общая процедура вызываемая при создании формы самостоятельного подтверждения
// 
Процедура ПодготовитьФормуПодтвержденияПриСоздании(КонтекстФормы) Экспорт
	
	РеестрИмен = ОпределитьБазовыеРеквизиты(КонтекстФормы);
	
	Параметры = КонтекстФормы.Параметры;
	
	КонтекстФормы[РеестрИмен.ДанныеПодтверждения] 		= Параметры.ДанныеПодтверждения;
	КонтекстФормы[РеестрИмен.НастройкиПользователя] 	= Параметры.НастройкиПользователя;
	КонтекстФормы[РеестрИмен.СпособПодтверждения] 		= Параметры.ДанныеПодтверждения.ВторичнаяАвторизация;

	КонтекстФормы.ВремяИстекло				= Ложь;
	КонтекстФормы.Сертификат				= Параметры.Сертификат;
	КонтекстФормы.ДанныеДокументов			= Параметры.ДанныеДокументов;
	КонтекстФормы.ПредставлениеДокументов 	= ПолучитьПредставлениеДокументов(КонтекстФормы.ДанныеДокументов);
	КонтекстФормы.ПредставлениеСертификата	= ПолучитьПредставлениеСертификата(КонтекстФормы.Сертификат);
	
	Если ЗначениеЗаполнено(Параметры.ЗаголовокФормы) Тогда
		КонтекстФормы.Заголовок = Параметры.ЗаголовокФормы;
	КонецЕсли;
	
КонецПроцедуры	

#КонецОбласти

#Область ВстроенноеПодтверждение

// Перезаполняет служебные данные формы в случае смены сертификата
//
// Параметры:
//  КонтекстФормы 	- ФормаКлиентскогоПриложения
//  Сертификат		- СправочникСсылка.СертификатыКлючейЭлектроннойПодписиИШифрования
//
Процедура ПодтверждениеПриИзмененииСертификата(КонтекстФормы, Сертификат) Экспорт
	
	НовыйСтатус = Ложь;
	РеестрИмен = ОпределитьБазовыеРеквизиты(КонтекстФормы);
	
	Если ЗначениеЗаполнено(Сертификат) Тогда
		
		ДанныеСертификата = ПроверитьВыбранныйСертификат(Сертификат);
		КонтекстФормы[РеестрИмен.ДанныеСертификата] = ДанныеСертификата;
		ДанныеПодтверждения = ДанныеВторичнойАвторизацииПоУмолчанию();
		
		ДополнитьДанныеПодтверждения(ДанныеПодтверждения);
		
		ДанныеПодтверждения.ЭтапЦикла = "Инициализация";
		НовыйСтатус = ДанныеСертификата.Облачный;
		
		Если ДанныеСертификата.Облачный 
			И ЗначениеЗаполнено(ДанныеСертификата.Ошибка) Тогда
			НовыйСтатус = Ложь;
		КонецЕсли;
		
		Если НовыйСтатус Тогда
			
			НастройкиПользователя = СервисКриптографииDSSСлужебный.ПолучитьНастройкиПользователя(ДанныеСертификата.УчетнаяЗапись);
			ДанныеПодтверждения.Сертификат = СервисКриптографииDSSКлиентСервер.НайтиСертификат(НастройкиПользователя, ДанныеСертификата.Идентификатор);
			ДанныеПодтверждения.ВерсияПодтверждения = СервисКриптографииDSSКлиентСервер.ИдентификаторВерсииСервера(НастройкиПользователя);	
			
			ДанныеПодтверждения.ТипПодтверждения = "Транзакция";
			ДанныеПодтверждения.Заголовок = НСтр("ru = 'Подписание данных'", ДанныеПодтверждения.КодЯзыка);
			
			ДанныеПодтверждения.ВторичнаяАвторизация = НастройкиПользователя.ВторичнаяАвторизация;
			ДанныеПодтверждения.СрокДействия = СервисКриптографииDSSСлужебный.ДатаСеанса() + 60 * 5;
			ДанныеПодтверждения.ГрафическийКод = "";
			ДанныеПодтверждения.ГрафическийКодВладелец = Неопределено;
			
			Авторизован = СервисКриптографииDSSКлиентСервер.УчетнаяЗаписьАвторизована(НастройкиПользователя, СервисКриптографииDSSСлужебный.ДатаСеанса());
			ДваЭтапа = НЕ ЗначениеРеквизитаФормы(КонтекстФормы, "БезПодтверждения", Ложь)
						ИЛИ НЕ Авторизован
						ИЛИ ДанныеПодтверждения.Сертификат.ТребуетсяПинКод;
						
			ДанныеПодтверждения.ПараметрыВариантаВстроенного.ЕстьАвторизация = НЕ Авторизован;
			
			Если НЕ ДваЭтапа Тогда
				ДанныеПодтверждения.ЭтапЦикла = "Начало";
			КонецЕсли;
			
			КонтекстФормы[РеестрИмен.Логин] = НастройкиПользователя.Ссылка;
			КонтекстФормы[РеестрИмен.ЗапомнитьПарольЛогина] = НастройкиПользователя.ЗапоминатьПароли;
			КонтекстФормы[РеестрИмен.ГрафическийКод] = "";
			
			ТекущийПароль = Неопределено;
			Если НастройкиПользователя.ПервичнаяАутентификация = Перечисления.СпособыАвторизацииDSS.Первичный_СертификатАвторизации Тогда
				ТекущийПароль = НастройкиПользователя.ПарольСертификата;
			Иначе
				ТекущийПароль = НастройкиПользователя.Пароль;
			КонецЕсли;
			
			ЗначениеПароля = СервисКриптографииDSSКлиентСервер.ПолучитьЗначениеПароля(ТекущийПароль, НастройкиПользователя.АвторизованныйПользователь);
			КонтекстФормы[РеестрИмен.ПарольЛогина] = ЗначениеПароля;
			
			КонтекстФормы[РеестрИмен.НастройкиПользователя] = СервисКриптографииDSSСлужебный.ЗакрытьНастройкиПользователя(НастройкиПользователя);
			КонтекстФормы[РеестрИмен.ДанныеПодтверждения] = ДанныеПодтверждения;
			КонтекстФормы[РеестрИмен.СпособПодтверждения] = ДанныеПодтверждения.ВторичнаяАвторизация;
			
		КонецЕсли;	

	Иначе
		КонтекстФормы[РеестрИмен.ДанныеСертификата] = ДанныеСертификатаПоУмолчанию();
		
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

// Готовит структуру с описанием используемых реквизитов формы.
// Для встроенного варианта важно исключить пересечения с локальными переменными и существующими реквизитам
// формы с помощью префикса в имени реквизита
//
// Параметры:
//  КонтекстФормы 		- ФормаКлиентскогоПриложения
//  ВстроенныйВариант 	- Булево
//
// Возвращаемое значение:
//  Структура
//
Функция ОпределитьБазовыеРеквизиты(КонтекстФормы = Неопределено, ВстроенныйВариант = Ложь)
	
	Если КонтекстФормы = Неопределено Тогда
		Результат = ОписаниеБазовыхРеквизитов(ВстроенныйВариант);
		
	ИначеЕсли ЗначениеРеквизитаФормы(КонтекстФормы, ИмяБазовогоРеквизита(), Null) = Null Тогда
		Результат = ОписаниеБазовыхРеквизитов(ВстроенныйВариант);
		КодЯзыка = СервисКриптографииDSSСлужебный.КодЯзыка();
		МассивРеквизитов = Новый Массив;

		ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, ИмяБазовогоРеквизита(), Новый ОписаниеТипов(),
						НСтр("ru = 'Набор реквизитов формы'", КодЯзыка), Ложь);
						
		КонтекстФормы.ИзменитьРеквизиты(МассивРеквизитов,);
		КонтекстФормы[ИмяБазовогоРеквизита()] = Результат;
		
	Иначе
		Результат = КонтекстФормы[ИмяБазовогоРеквизита()];
		
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

Функция ОписаниеБазовыхРеквизитов(ВстроенныйВариант = Ложь)
	
	РеестрРеквизитов = Новый Структура;
	РеестрРеквизитов.Вставить("ЗапомнитьПарольЛогина", "");
	РеестрРеквизитов.Вставить("СпособПодтверждения", "");
	РеестрРеквизитов.Вставить("НастройкиПользователя", "");
	РеестрРеквизитов.Вставить("ДанныеПодтверждения", "");
	РеестрРеквизитов.Вставить("ДанныеСертификата", "");
	РеестрРеквизитов.Вставить("КодПодтверждения", "");
	РеестрРеквизитов.Вставить("ОжидатьВыполнения", "");
	РеестрРеквизитов.Вставить("ИнформацияСервера", "");
	РеестрРеквизитов.Вставить("Логин", "");
	РеестрРеквизитов.Вставить("ПарольЛогина", "");
	РеестрРеквизитов.Вставить("ГрафическийКод", "");
	РеестрРеквизитов.Вставить("ИменаГруппКонтейнера", "");
	РеестрРеквизитов.Вставить("ПодтверждениеТипОперации", "");
	РеестрРеквизитов.Вставить("ПодтверждениеПредставлениеСертификата", "");
	РеестрРеквизитов.Вставить("ПодтверждениеДанныеСертификата", "");
	РеестрРеквизитов.Вставить("ПодтверждениеШаг1", "");
	РеестрРеквизитов.Вставить("ПодтверждениеШаг2", "");
	РеестрРеквизитов.Вставить("ПодтверждениеШаг3", "");
	
	ПрефиксИмени = "";
	Если ВстроенныйВариант Тогда
		ПрефиксИмени = "DSS_";
	КонецЕсли;
	
	Для Каждого СтрокаКлюча Из РеестрРеквизитов Цикл
		РеестрРеквизитов[СтрокаКлюча.Ключ] = ПрефиксИмени + СтрокаКлюча.Ключ;
	КонецЦикла;
	
	РеестрРеквизитов.Вставить("ИменаЭлементовФормы", Новый Структура);
	РеестрРеквизитов.Вставить("ИспользоватьПрефикс", ВстроенныйВариант);

	Возврат РеестрРеквизитов;
	
КонецФункции
	
// Формирует массив способов авторизации по входящим данным
//
// Параметры:
//  ВариантыАвторизации - Строка, ПеречислениеСсылка.СпособыАвторизацииDSS, Массив - если передан массив, 
//						то он может быть строкой или перечислением.
//
Функция СформироватьСписокМетодовАвторизации(ВариантыАвторизации)
	
	Результат = Новый Массив;
	
	Если ТипЗнч(ВариантыАвторизации) <> Тип("Массив") Тогда
		ОбщийСписок = Новый Массив;
		ОбщийСписок.Добавить(ВариантыАвторизации);
	Иначе
		ОбщийСписок = ВариантыАвторизации;
	КонецЕсли;
	
	Для Каждого СтрокаМассива Из ОбщийСписок Цикл
		ТекущееЗначение = ПолучитьЗначениеПеречисления(СтрокаМассива);
		Если ЗначениеЗаполнено(ТекущееЗначение) Тогда
			Результат.Добавить(ТекущееЗначение);
		КонецЕсли;	
	КонецЦикла;
	
	Возврат Результат;
	
КонецФункции

// Преобразует строковое представление Перечисления.СпособыАвторизацииDSS в случае необходимости
//
// Параметры:
//  ТекущееЗначение - Строка
//                  - ПеречислениеСсылка.СпособыАвторизацииDSS
//
// Возвращаемое значение:
//  ПеречислениеСсылка.СпособыАвторизацииDSS
//	
Функция ПолучитьЗначениеПеречисления(ТекущееЗначение)
	
	Результат = Неопределено;
	
	Если ТипЗнч(ТекущееЗначение) = Тип("Строка") Тогда
		Результат = Перечисления.СпособыАвторизацииDSS[ТекущееЗначение];
	Иначе
		Результат = ТекущееЗначение;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции	

// Подготавливает структуру "ДанныеСертификата" для встроенного подтверждения
//
Функция ДанныеСертификатаПоУмолчанию()
	
	Результат = Новый Структура;
	Результат.Вставить("Облачный", Ложь);
	Результат.Вставить("Ошибка", "");
	Результат.Вставить("Отпечаток", "");
	Результат.Вставить("УчетнаяЗапись", Справочники.УчетныеЗаписиDSS.ПустаяСсылка());
	Результат.Вставить("Идентификатор", 0);
	
	Возврат Результат;
	
КонецФункции

// Дополняет данные цикла подтверждения реквизитами для работы во встроенном режиме
//
Процедура ДополнитьДанныеПодтверждения(ДанныеПодтверждения)
	
	ДанныеПодтверждения.ПараметрыВариантаВстроенного.Вставить("ЕстьАвторизация", Ложь);
	ДанныеПодтверждения.ПараметрыВариантаВстроенного.Вставить("ПинКод", "");// данное поле задействовано в интегрированных формах
	ДанныеПодтверждения.ПараметрыВариантаВстроенного.Вставить("ПинКодПроверен", Ложь);
	ДанныеПодтверждения.ПараметрыВариантаВстроенного.Вставить("ПакетнаяОперация", Ложь);
	ДанныеПодтверждения.ПараметрыВариантаВстроенного.Вставить("ТипРезультата", Неопределено);
	ДанныеПодтверждения.ПараметрыВариантаВстроенного.Вставить("ПарольВПамяти", Ложь);
		
КонецПроцедуры		

// Безопасное получение реквизиты формы, с проверка его наличия
//
Функция ЗначениеРеквизитаФормы(КонтекстФормы, ИмяРеквизита, ЗначениеПоУмолчанию = Неопределено)
	
	Результат = ЗначениеПоУмолчанию;
	
	ИщемСвойство = Новый Структура(ИмяРеквизита);
	ЗаполнитьЗначенияСвойств(ИщемСвойство, КонтекстФормы);
	
	Если ИщемСвойство[ИмяРеквизита] <> Неопределено Тогда
		Результат = ИщемСвойство[ИмяРеквизита];
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Создает дополнительные реквизиты формы для встроенного подтверждения
//
Процедура ПодготовитьГруппуПодтвержденияРеквизиты(КонтекстФормы, КонвертироватьИмена = Истина)
	
	ОпределитьБазовыеРеквизиты(КонтекстФормы, КонвертироватьИмена);
	
	// создать реквизиты формы и инициализируем значения
	КодЯзыка = СервисКриптографииDSSСлужебный.КодЯзыка();
	МассивРеквизитов = Новый Массив;
	
	// - представление галки запомнить пароль
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ЗапомнитьПарольЛогина", Новый ОписаниеТипов("Булево"), 
				НСтр("ru = 'Запомнить пароль'", КодЯзыка));
	// - представление способа подтверждения
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "СпособПодтверждения", Новый ОписаниеТипов(),
				НСтр("ru = 'Запомнить пароль'", КодЯзыка));
	// - структура сессионных данных
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "НастройкиПользователя", Новый ОписаниеТипов(),
					НСтр("ru = 'Настройки пользователя'", КодЯзыка));
	// - структура содержит данные цикла обмена с сервисом
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ДанныеПодтверждения", Новый ОписаниеТипов(),
					НСтр("ru = 'Данные подтверждения'", КодЯзыка));
	// - структура содержит общие данные выбранного сертификата
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ДанныеСертификата", Новый ОписаниеТипов(),
					НСтр("ru = 'Данные сертификата'", КодЯзыка));
	// - данные поля ввода для кода подтверждения
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "КодПодтверждения", Новый ОписаниеТипов("Строка"),
					НСтр("ru = 'Код подтверждения'", КодЯзыка));
	// - признак для блокировки повторного запроса на сервер
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ОжидатьВыполнения", Новый ОписаниеТипов("Булево"),
					НСтр("ru = 'Ожидать подтверждения'", КодЯзыка));
	// - строка полученная от сервера
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ИнформацияСервера", Новый ОписаниеТипов("Строка"),
					НСтр("ru = 'Информация сервера'", КодЯзыка));
	// - справочник учетных записей
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "Логин", Новый ОписаниеТипов("СправочникСсылка.УчетныеЗаписиDSS"),
					НСтр("ru = 'Логин'", КодЯзыка));
	// - пароль или пин-код для логина
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ПарольЛогина", Новый ОписаниеТипов("Строка"),
					НСтр("ru = 'Пароль пользователя'", КодЯзыка));
	// - адрес графического кода во временном хранилище
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ГрафическийКод", Новый ОписаниеТипов("Строка"),
					НСтр("ru = 'Графический код'", КодЯзыка));
	// - имя группы контейнера
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ИменаГруппКонтейнера", Новый ОписаниеТипов(),
					НСтр("ru = 'Имя группы'", КодЯзыка));
	// - идентификатор типа операции
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ПодтверждениеТипОперации", Новый ОписаниеТипов("Строка"),
					НСтр("ru = 'Идентификатор типа операции'", КодЯзыка));
	// - представление состояние сертификата авторизации
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ПодтверждениеПредставлениеСертификата", Новый ОписаниеТипов("Строка"),
					НСтр("ru = 'Состояние сертификата'", КодЯзыка));
	// - структура содержит общие данные выбранного сертификата
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ПодтверждениеДанныеСертификата", Новый ОписаниеТипов(),
					НСтр("ru = 'Данные сертификата авторизации'", КодЯзыка));
					
	// - служебные реквизиты для оформления
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ПодтверждениеШаг1", Новый ОписаниеТипов("Число"));
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ПодтверждениеШаг2", Новый ОписаниеТипов("Число"));
	ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, "ПодтверждениеШаг3", Новый ОписаниеТипов("Число"));
					
	КонтекстФормы.ИзменитьРеквизиты(МассивРеквизитов,);
	
КонецПроцедуры

// Добавляет новый реквизит в форме. Также производится проверка на существование такого реквизита.
// Может потребоваться в случае индивидуального оформления формы, но тип реквизиты должен соответствовать ожидаемому.
//
Функция ДобавитьНовыйРеквизит(КонтекстФормы, МассивРеквизитов, ИмяНовогоРеквизита, ТипРеквизита, ЗаголовокРеквизита = "", КонвертацияИмени = Истина)
	
	Результат = Ложь;
	Если КонвертацияИмени Тогда
		РеестрИмен = ОпределитьБазовыеРеквизиты(КонтекстФормы);
		НовоеИмя = РеестрИмен[ИмяНовогоРеквизита];
	Иначе
		НовоеИмя = ИмяНовогоРеквизита;
	КонецЕсли;

	ИщемПоле = Новый Структура(НовоеИмя, Null);
	ЗаполнитьЗначенияСвойств(ИщемПоле, КонтекстФормы);
	
	Если ИщемПоле[НовоеИмя] = Null Тогда
		НовыйРеквизит = Новый РеквизитФормы(НовоеИмя, ТипРеквизита, ,	ЗаголовокРеквизита);
		МассивРеквизитов.Добавить(НовыйРеквизит);
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Производит начальное заполнение добавленных реквизитов для встроенного подтверждения
//
Процедура ПодготовитьГруппуПодтвержденияИнициализация(КонтекстФормы)
	
	РеестрИмен = ОпределитьБазовыеРеквизиты(КонтекстФормы);
	КонтекстФормы[РеестрИмен.ЗапомнитьПарольЛогина] = Истина;
	КонтекстФормы[РеестрИмен.ДанныеСертификата] = ДанныеСертификатаПоУмолчанию();
	КонтекстФормы[РеестрИмен.ДанныеПодтверждения] = ДанныеВторичнойАвторизацииПоУмолчанию();
	КонтекстФормы[РеестрИмен.НастройкиПользователя] = СервисКриптографииDSS.НастройкиПользователяПоУмолчанию();
	КонтекстФормы[РеестрИмен.ИменаГруппКонтейнера] = Новый Структура;
	ДополнитьДанныеПодтверждения(КонтекстФормы[РеестрИмен.ДанныеПодтверждения]);

КонецПроцедуры

// Проверяет, была ли подготовлена форма для встроенного подтверждения
//
Функция ФормаПодготовлена(КонтекстФормы)
	
	ВсеСвойства = Новый Структура(ИмяБазовогоРеквизита(), Неопределено);
	ЗаполнитьЗначенияСвойств(ВсеСвойства, КонтекстФормы);
	Результат = ВсеСвойства[ИмяБазовогоРеквизита()] <> Неопределено;
	Возврат Результат;
	
КонецФункции

// Добавляет нужные элементы на форму для встроенного подтверждения
//
Процедура ПодготовитьГруппуПодтвержденияЭлементы(КонтекстФормы, ТекущиеЭлементыФормы)
	
	РеестрИмен 		= ОпределитьБазовыеРеквизиты(КонтекстФормы);
	ИменаЭлементов	= РеестрИмен.ИменаЭлементовФормы;
	ОбщегоНазначенияКлиентСервер.ДополнитьСтруктуру(ИменаЭлементов, ТекущиеЭлементыФормы, Истина);
	СписокГрупп		= КонтекстФормы[РеестрИмен.ИменаГруппКонтейнера];
	
	КодЯзыка		= СервисКриптографииDSSСлужебный.КодЯзыка();
	ЭлементыФормы	= КонтекстФормы.Элементы;
	ИспользованиеВозможно = СервисКриптографииDSS.ИспользоватьСервисОблачнойПодписи();
	
	КонтейнерОбщий	= ЭлементыФормы[СписокГрупп.ГруппаСертификата];
	КонтейнерПервый = ЭлементыФормы[СписокГрупп.КонтейнерЭлементов1];
	КонтейнерВторой = КонтейнерПервый;
	КонтейнерКоманд	= КонтейнерПервый;
	
	Если ЗначениеЗаполнено(СписокГрупп.КонтейнерЭлементов2) Тогда
		КонтейнерВторой = КонтекстФормы.Элементы[СписокГрупп.КонтейнерЭлементов2];
	КонецЕсли;	

	Если ЗначениеЗаполнено(СписокГрупп.ГруппаКоманды) Тогда
		КонтейнерКоманд	= КонтекстФормы.Элементы[СписокГрупп.ГруппаКоманды];
	КонецЕсли;
	
	ЕстьРазделители = СписокГрупп.ЕстьРазделители И ИспользованиеВозможно;
	
	ЭлементФормы = ДобавитьРазделитель(ЭлементыФормы, РеестрИмен, ЕстьРазделители, "ПодтверждениеРазделитель1", КонтейнерОбщий, "1", "Первый");
	ЭлементФормы = ДобавитьРазделитель(ЭлементыФормы, РеестрИмен, ЕстьРазделители, "ПодтверждениеРазделитель2", КонтейнерПервый, "2");
	ГруппаПодтвержденияУчетнаяЗапись = ДобавитьГруппу(ЭлементыФормы, ИменаЭлементов, "ГруппаПодтвержденияУчетнаяЗапись", КонтейнерПервый);
	ГруппаПодтвержденияУчетнаяЗаписьВеб = ДобавитьГруппу(ЭлементыФормы, ИменаЭлементов, "ГруппаПодтвержденияУчетнаяЗаписьВеб", КонтейнерПервый);
	ЭлементФормы = ДобавитьРазделитель(ЭлементыФормы, РеестрИмен, ЕстьРазделители, "ПодтверждениеРазделитель3", КонтейнерПервый, "3");
	ГруппаПодтвержденияОписание = ДобавитьГруппу(ЭлементыФормы, ИменаЭлементов, "ГруппаПодтвержденияОписание", КонтейнерПервый);
	ГруппаПодтвержденияВыбор = ДобавитьГруппу(ЭлементыФормы, ИменаЭлементов, "ГруппаПодтвержденияВыбор", КонтейнерПервый);
	ГруппаПодтвержденияОнлайн = ДобавитьГруппу(ЭлементыФормы, ИменаЭлементов, "ГруппаПодтвержденияОнлайн", КонтейнерВторой);
	ГруппаПодтвержденияОфлайн = ДобавитьГруппу(ЭлементыФормы, ИменаЭлементов, "ГруппаПодтвержденияОфлайн", КонтейнерВторой);
	ГруппаПодтвержденияКод = ДобавитьГруппу(ЭлементыФормы, ИменаЭлементов, "ГруппаПодтвержденияКод", КонтейнерКоманд);
	Если КонтейнерКоманд = КонтейнерПервый Тогда
		ЭлементФормы = ДобавитьРазделитель(ЭлементыФормы, РеестрИмен, ЕстьРазделители, "ПодтверждениеРазделитель4", КонтейнерВторой);
	КонецЕсли;	
	
	ГруппаПодтвержденияУчетнаяЗапись.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Вертикальная;
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеЛогин", НСтр("ru = 'Уч. запись'", КодЯзыка), ГруппаПодтвержденияУчетнаяЗапись, , "ПолеВвода");
	УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, "Логин");
	ЭлементФормы.ТолькоПросмотр = Истина;
	
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеПредставлениеСертификата", НСтр("ru = 'Сертификат авторизации'", КодЯзыка), ГруппаПодтвержденияУчетнаяЗапись, , "ПолеВвода");
	УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, "ПодтверждениеПредставлениеСертификата");
	ЭлементФормы.ВысотаЗаголовка = 2;
	ЭлементФормы.КнопкаВыбора = Истина;
	ЭлементФормы.КартинкаКнопкиВыбора = БиблиотекаКартинок.ОткрытьФайл;
	ЭлементФормы.РедактированиеТекста = Ложь;
	ЭлементФормы.ПропускатьПриВводе = Истина;
	ЭлементФормы.РастягиватьПоГоризонтали = Ложь;
	ЭлементФормы.ПодсказкаВвода = НСтр("ru = 'Загрузите сертификат авторизации'", КодЯзыка);
	ЭлементФормы.УстановитьДействие("НачалоВыбора", "Подключаемый_ПодтверждениеНачалоВыбора");
	
	ВременнаяГруппа = ДобавитьГруппу(ЭлементыФормы, ИменаЭлементов, "ГруппаПодтверждениеПарольЗапомнить", ГруппаПодтвержденияУчетнаяЗапись);
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеПароль", НСтр("ru = 'Пароль'", КодЯзыка), ВременнаяГруппа, , "ПолеВвода");
	УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, "ПарольЛогина");
	ЭлементФормы.ПропускатьПриВводе = Ложь;
	ЭлементФормы.РежимПароля = Истина;
	ЭлементФормы.РастягиватьПоГоризонтали = Ложь;
	ЭлементФормы.ОграничениеТипа = Новый ОписаниеТипов("Строка");
	ЭлементФормы.ПодсказкаВвода = НСтр("ru = 'введите пароль'", КодЯзыка);
	ЭлементФормы.УстановитьДействие("ПриИзменении", "Подключаемый_ПодтверждениеПриИзменении");
	
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеЗапомнитьПарольЛогина", НСтр("ru = 'Запомнить пароль'", КодЯзыка), ВременнаяГруппа, , "ПолеФлажка");
	УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, "ЗапомнитьПарольЛогина");
	ЭлементФормы.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Право;
	ЭлементФормы.ОтображениеПодсказки = ОтображениеПодсказки.Кнопка;
	ЭлементФормы.Подсказка = НСтр("ru = 'Пароль сохраняется на время сессии работы в 1С'", КодЯзыка);
	ЭлементФормы.УстановитьДействие("ПриИзменении", "Подключаемый_ПодтверждениеПриИзменении");
	
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеПредупреждениеВеб", "Пример", ГруппаПодтвержденияУчетнаяЗаписьВеб, "ДекорацияФормы");
	ЭлементФормы.Заголовок = НСтр("ru = 'Требуется авторизация на сервере DSS'", КодЯзыка);
	
	ТекущаяКоманда = ДобавитьКоманду(КонтекстФормы, ИменаЭлементов, "ПодтверждениеАвторизация");
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеАвторизация", НСтр("ru = 'Авторизация'", КодЯзыка), ГруппаПодтвержденияУчетнаяЗаписьВеб, "КнопкаФормы");
	УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, ТекущаяКоманда.Имя, "ИмяКоманды");
	ЭлементФормы.Вид = ВидКнопкиФормы.Гиперссылка;
	
	ГруппаПодтвержденияВыбор.Группировка = ГруппировкаПодчиненныхЭлементовФормы.Вертикальная;
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеСпособПодтверждения", НСтр("ru = 'Способ подтверждения'", КодЯзыка), ГруппаПодтвержденияВыбор, , "ПолеВвода");
	УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, "СпособПодтверждения");
	ЭлементФормы.ВысотаЗаголовка = 2;
	ЭлементФормы.РежимВыбораИзСписка = Истина;
	ЭлементФормы.РедактированиеТекста = Ложь;
	ЭлементФормы.КнопкаВыбора = Ложь;
	ЭлементФормы.УстановитьДействие("ПриИзменении", "Подключаемый_ПодтверждениеПриИзменении");
	ЭлементФормы.ОтображениеПодсказки = ОтображениеПодсказки.Кнопка;
	ЭлементФормы.РасширеннаяПодсказка.УстановитьДействие("ОбработкаНавигационнойСсылки", "Подключаемый_ПодтверждениеОбработкаНавигационнойСсылки");
	ЭлементФормы.АвтоОтметкаНезаполненного = Истина;

	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеИнформацияСервераЗаголовок", "", ГруппаПодтвержденияОписание, "ДекорацияФормы", "Надпись");
	ЭлементФормы.Высота = 2;
	ЭлементФормы.Ширина = 9;
	ЭлементФормы.РастягиватьПоГоризонтали = Ложь;
	ЭлементФормы.АвтоМаксимальнаяВысота = Ложь;
	ЭлементФормы.АвтоМаксимальнаяШирина = Ложь;
	
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеИнформацияСервера", НСтр("ru = 'Сообщение сервиса'", КодЯзыка), ГруппаПодтвержденияОписание, , "ПолеНадписи");
	УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, "ИнформацияСервера");
	ЭлементФормы.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
	ЭлементФормы.ЦветТекста = СервисКриптографииDSSСлужебный.ПолучитьЭлементСтиля("ПодтверждениеОперацииОписаниеЦвет", "Цвет");
	ЭлементФормы.АвтоМаксимальнаяВысота = Ложь;
	ЭлементФормы.АвтоМаксимальнаяШирина = Ложь;
	ЭлементФормы.РастягиватьПоГоризонтали = Истина;
	ЭлементФормы.РастягиватьПоВертикали = Истина;
	
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеКодПодтверждения", НСтр("ru = 'Код подтверждения'", КодЯзыка), ГруппаПодтвержденияКод, , "ПолеВвода");
	УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, "КодПодтверждения");
	ЭлементФормы.ВысотаЗаголовка = 2;
	ЭлементФормы.Ширина = 8;
	ЭлементФормы.ПропускатьПриВводе = Ложь;
	ЭлементФормы.РастягиватьПоГоризонтали = Ложь;
	ЭлементФормы.РастягиватьПоВертикали = Ложь;
	ЭлементФормы.ОбновлениеТекстаРедактирования = ОбновлениеТекстаРедактирования.ПриИзмененииЗначения;
	ЭлементФормы.УстановитьДействие("ПриИзменении", "Подключаемый_ПодтверждениеПриИзменении");
	
	ТекущаяКоманда = ДобавитьКоманду(КонтекстФормы, ИменаЭлементов, "ПодтверждениеОК");
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеОК", "ОК", ГруппаПодтвержденияКод, "КнопкаФормы");
	УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, ТекущаяКоманда.Имя, "ИмяКоманды");
	ЭлементФормы.ПропускатьПриВводе = Ложь;
	
	ГруппаИнструкции = ДобавитьГруппу(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеИнструкция", ГруппаПодтвержденияКод, , , НСтр("ru = 'Требуется помощь?'", КодЯзыка));
	ГруппаИнструкции.Поведение = ПоведениеОбычнойГруппы.Всплывающая;
	ГруппаИнструкции.Отображение = ОтображениеОбычнойГруппы.Нет;
	ГруппаИнструкции.ВертикальноеПоложениеВГруппе = ВертикальноеПоложениеЭлемента.Центр;
	
	ТекстИнструкции = НСтр("ru = '1. Откройте мобильное приложение на своем устройстве.
									|2. Наведите камеру устройства на QR-код.
									|3. Введите код подтверждения или код отказа.'");
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеСодержаниеИнструкции", ТекстИнструкции, ГруппаИнструкции, "ДекорацияФормы", "Надпись");
	
	ТекущаяКоманда = ДобавитьКоманду(КонтекстФормы, ИменаЭлементов, "ПодтверждениеПовторить");
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеПовторить", НСтр("ru = 'Выслать заново'", КодЯзыка), ГруппаПодтвержденияКод, "КнопкаФормы");
	УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, ТекущаяКоманда.Имя, "ИмяКоманды");
	ЭлементФормы.Ширина = 13;
	
	ГруппаПодтвержденияОнлайн.ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеЭлемента.Центр;
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеАнимация", НСтр("ru = 'Анимация'", КодЯзыка), ГруппаПодтвержденияОнлайн, "ДекорацияФормы", "Картинка");
	ЭлементФормы.ТекстНевыбраннойКартинки = НСтр("ru = 'Анимация'", КодЯзыка);
	ЭлементФормы.РастягиватьПоГоризонтали = Истина;
	ЭлементФормы.Картинка = БиблиотекаКартинок.АнимацияПодтверждения;
	ЭлементФормы.Рамка = СервисКриптографииDSSСлужебный.ПолучитьЭлементСтиля("ПоУмолчанию", "Рамка");
	ЭлементФормы.Высота = 9;
	ЭлементФормы.Ширина = 23;
	
	ГруппаПодтвержденияОфлайн.ГоризонтальноеПоложениеВГруппе = ГоризонтальноеПоложениеЭлемента.Центр;
	ГруппаПодтвержденияОфлайн.ВертикальноеПоложениеПодчиненных = ВертикальноеПоложениеЭлемента.Центр;
	ГруппаПодтвержденияОфлайн.Высота = 14;
	ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, "ПодтверждениеГрафическийКод", "QR-code", ГруппаПодтвержденияОфлайн, , "ПолеКартинки");
	УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, "ГрафическийКод");
	ЭлементФормы.РастягиватьПоГоризонтали = Истина;
	ЭлементФормы.Высота = 9;
	ЭлементФормы.Ширина = 23;
	ЭлементФормы.РазмерКартинки = РазмерКартинки.Пропорционально;
	ЭлементФормы.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
	ЭлементФормы.ТекстНевыбраннойКартинки = НСтр("ru = 'Код для сканирования'", КодЯзыка);
	ЭлементФормы.Рамка = СервисКриптографииDSSСлужебный.ПолучитьЭлементСтиля("ПоУмолчанию", "Рамка");
	
КонецПроцедуры

// Служебная функция, устанавливает путь к данным, если нужно
Процедура УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, ПутьКДанным, КлючевойРеквизит = "ПутьКДанным")
	
	Если РеестрИмен.Свойство(ПутьКДанным) Тогда
		НовоеИмя = РеестрИмен[ПутьКДанным];
	Иначе
		НовоеИмя = ПутьКДанным;
	КонецЕсли;
	
	Если ПустаяСтрока(ЭлементФормы[КлючевойРеквизит]) Тогда
		ЭлементФормы[КлючевойРеквизит] = НовоеИмя;
	КонецЕсли;
	
	Если КлючевойРеквизит = "ПутьКДанным" Тогда
		РеестрИмен.Вставить(ПутьКДанным, ЭлементФормы[КлючевойРеквизит]);
	КонецЕсли;
	
КонецПроцедуры

// Служебная функция добавления группы элементов для разделителя шага подтверждения
//
Функция ДобавитьРазделитель(ЭлементыФормы, РеестрИмен, СоздаватьРазделитель, ИмяЭлемента, ЭлементВладелец, ДобавитьНомер = "", ЭлементВставки = Неопределено)
	
	ИменаЭлементов	= РеестрИмен.ИменаЭлементовФормы;

	НовоеИмя = "";
	Если НЕ ИменаЭлементов.Свойство(ИмяЭлемента, НовоеИмя) Тогда
		НовоеИмя = "DSS_" + ИмяЭлемента;
		ИменаЭлементов.Вставить(ИмяЭлемента, НовоеИмя);
	КонецЕсли;

	ВладелецГруппа = ЭлементВладелец;
	
	Если СоздаватьРазделитель Тогда
		ВладелецГруппа = ДобавитьГруппу(ЭлементыФормы, ИменаЭлементов, ИмяЭлемента, ЭлементВладелец, , ЭлементВставки);
		ВладелецГруппа.ВертикальноеПоложениеПодчиненных = ВертикальноеПоложениеЭлемента.Центр;
		
		Если ЗначениеЗаполнено(ДобавитьНомер) Тогда
			ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, ИмяЭлемента + "Номер", "", ВладелецГруппа, "ПолеФормы", "ПолеКартинки");
			УстановитьПутьКДанным(ЭлементФормы, РеестрИмен, "ПодтверждениеШаг" + ДобавитьНомер);
			ЭлементФормы.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Нет;
			ЭлементФормы.Рамка = СервисКриптографииDSSСлужебный.ПолучитьЭлементСтиля("ПоУмолчанию", "Рамка");
			ЭлементФормы.КартинкаЗначений = БиблиотекаКартинок.ЭтапыПодтверждения;
			ЭлементФормы.РастягиватьПоГоризонтали = Ложь;
		КонецЕсли;	
		
		ЭлементФормы = ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, ИмяЭлемента + "Линия", "", ВладелецГруппа, "ДекорацияФормы", "Картинка");
		ЭлементФормы.АвтоМаксимальнаяШирина = Ложь;
		ЭлементФормы.АвтоМаксимальнаяВысота = Ложь;
		ЭлементФормы.РастягиватьПоГоризонтали = Истина;
		ЭлементФормы.РастягиватьПоВертикали = Ложь;
		ЭлементФормы.Высота = 1;
		ЭлементФормы.Картинка = БиблиотекаКартинок.РазделительШагов;
		ЭлементФормы.РазмерКартинки = РазмерКартинки.Растянуть;

	КонецЕсли;	
	
	Возврат ВладелецГруппа;
	
КонецФункции

// Служебная функция добавления группы формы
//
Функция ДобавитьГруппу(ЭлементыФормы, ИменаЭлементов, ИмяГруппы, ЭлементВладелец, ТипГруппы = "ГруппаФормы", ЭлементВставки = Неопределено, Заголовок = "")
	
	НовоеИмя = "";
	Если НЕ ИменаЭлементов.Свойство(ИмяГруппы, НовоеИмя) Тогда
		НовоеИмя = "DSS_" + ИмяГруппы;
		ИменаЭлементов.Вставить(ИмяГруппы, НовоеИмя);
	КонецЕсли;

	КудаВставить = ЭлементВставки;
	Если ЭлементВставки = "Первый" Тогда
		КудаВставить = ЭлементВладелец.ПодчиненныеЭлементы[0];
	КонецЕсли;
	
	НашлиЭлемент = ЭлементыФормы.Найти(НовоеИмя);
	Если НашлиЭлемент = Неопределено Тогда
		Результат = ЭлементыФормы.Вставить(НовоеИмя, Тип(ТипГруппы), ЭлементВладелец, КудаВставить);
	Иначе
		Результат = НашлиЭлемент;
	КонецЕсли;	
	
	Результат.Вид = ВидГруппыФормы.ОбычнаяГруппа;
	Результат.Группировка = ГруппировкаПодчиненныхЭлементовФормы.ГоризонтальнаяВсегда;
	Результат.РастягиватьПоВертикали = Ложь;
	Результат.СквозноеВыравнивание = СквозноеВыравнивание.Использовать;
	Результат.РастягиватьПоГоризонтали = Неопределено;
	Результат.Видимость = Ложь;
	
	Если ЗначениеЗаполнено(Заголовок) Тогда
		Результат.Заголовок = Заголовок;
		Результат.ОтображатьЗаголовок = Истина;
		Результат.Отображение = ОтображениеОбычнойГруппы.ОбычноеВыделение;
	Иначе
		Результат.ОтображатьЗаголовок = Ложь;
		Результат.Отображение = ОтображениеОбычнойГруппы.Нет;
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

// Служебная функция для добавления элемента формы различных видов
//
Функция ДобавитьЭлемент(ЭлементыФормы, ИменаЭлементов, ИмяЭлемента, ЗаголовокЭлемента, ЭлементВладелец, ТипЭлемента = "ПолеФормы", ВидПоля = "")
	
	НовоеИмя = "";
	Если НЕ ИменаЭлементов.Свойство(ИмяЭлемента, НовоеИмя) Тогда
		НовоеИмя = "DSS_" + ИмяЭлемента;
		ИменаЭлементов.Вставить(ИмяЭлемента, НовоеИмя);
	КонецЕсли;
	
	НашлиЭлемент = ЭлементыФормы.Найти(НовоеИмя);
	Если НашлиЭлемент = Неопределено Тогда
		Результат = ЭлементыФормы.Добавить(НовоеИмя, Тип(ТипЭлемента), ЭлементВладелец);
	Иначе
		Результат = НашлиЭлемент;
	КонецЕсли;
	
	Результат.Заголовок = ЗаголовокЭлемента;
	
	Если ТипЭлемента = "КнопкаФормы" Тогда
		Результат.АвтоМаксимальнаяШирина = Ложь;
		Результат.АвтоМаксимальнаяВысота = Ложь;
		Результат.РастягиватьПоГоризонтали = Ложь;
	КонецЕсли;
	
	Если ЗначениеЗаполнено(ВидПоля) Тогда
		Если ТипЭлемента = "ПолеФормы" Тогда
			Результат.Вид = ВидПоляФормы[ВидПоля];
			Результат.ПропускатьПриВводе = Истина;
			Результат.ПоложениеЗаголовка = ПоложениеЗаголовкаЭлементаФормы.Лево;
		ИначеЕсли ТипЭлемента = "ДекорацияФормы" Тогда
			Результат.Вид = ВидДекорацииФормы[ВидПоля];
		КонецЕсли;
	КонецЕсли;	
	
	Возврат Результат;
	
КонецФункции

// Служебная функция для добавления команды формы
//
Функция ДобавитьКоманду(КонтекстФормы, ИменаЭлементов, ИмяКоманды)
	
	НовоеИмя = "";
	Если НЕ ИменаЭлементов.Свойство(ИмяКоманды, НовоеИмя) Тогда
		НовоеИмя = "DSS_" + ИмяКоманды;
		ИменаЭлементов.Вставить(ИмяКоманды, НовоеИмя);
	КонецЕсли;
	
	НоваяКоманда = КонтекстФормы.Команды.Добавить(НовоеИмя);
	НоваяКоманда.Действие = "Подключаемый_ПодтверждениеОбработкаКоманды";
	
	Возврат НоваяКоманда;
	
КонецФункции

Функция ИмяБазовогоРеквизита()
	
	Возврат "DSS_НаборРеквизитовФормы";
	
КонецФункции

// Получает значение настроек подключения к сервису из формы
// 
// Параметры:
//  ЭлементыФормы	- ФормаКлиентскогоПриложения
//  РеестрИмен		- Структура
//            		- Неопределено
//
// Возвращаемое значение:
//   см. СервисКриптографииDSS.НастройкиПользователяПоУмолчанию
//
Функция ПолучитьНастройкиПользователяИзФормы(КонтекстФормы, РеестрИмен = Неопределено)
	
	Если РеестрИмен = Неопределено Тогда
		РеестрИмен = ОпределитьБазовыеРеквизиты(КонтекстФормы);
	КонецЕсли;
	
	Результат = КонтекстФормы[РеестрИмен.НастройкиПользователя];
	
	Возврат Результат;
	
КонецФункции

#КонецОбласти